﻿const Rule = require('./Rule');
const cheerio = require('cheerio');
const logger = require('../logs/logger');
const msgHelper = require('../dts/msgHelper');
const url = require('url');
const qs = require('querystring');
const moment = require('moment');
const injector = require('../injector/injector');
const fs = require('fs');
const brandSvr = require('../svrs/brandSvr');

// privates 

_args = {};

const scrollJs = `<script>${fs.readFileSync('injector/scroll.js', 'utf-8')}</script>`;
const redirectJs = `<script>${fs.readFileSync('injector/redirect.js', 'utf-8')}</script>`;

function regSearch(raw, pattern) {
    return pattern.exec(raw)[1]
        .replace(/undefined/g, '')
        .replace(/"/g, '')
        .replace(/\|/g, '')
        .trim();
}

function regEval(raw, pattern) {
    return eval(pattern.exec(raw)[1]);
}

function regReplaceQuot(raw, pattern) {
    return pattern.exec(raw)[1]
        .replace(/\&quot;/g, '"');
}

function forbiddenCache(resp) {
    let header = Object.assign({}, resp.response.header);
    delete header['Content-Security-Policy'];
    delete header['Content-Security-Policy-Report-Only'];
    header['Expires'] = 0;
    header['Cache-Control'] = 'no-cache, no-store, must-revalidate';
    resp.response.header = header;
}

// privates

class ProfileRule extends Rule {
    constructor(args) { super(args); _args = args; }

    get name() { return 'profile rule'; }

    get enable() { return true; }

    isMatch(req, resp) {
        return req.url.indexOf('mp.weixin.qq.com/mp/profile_ext?') > -1 &&
            req.requestOptions.method === 'GET';
    }

    fake(req) {
        // if (req.requestOptions.method !== 'GET') return;

        // var q = qs.parse(url.parse(req.url).query);

        // if (q.action && q.action === 'home') {

        //     q.count = 10000;
        //     // req.url = qs.stringify(q);

        //     req.url = 'http://www.baidu.com';

        //     // logger.debug(req.requestData.toString());
        // } 

    }

    async execute(req, resp) {
        var q = qs.parse(url.parse(req.url).query);
        var msgs = [];
        var response = resp.response;

        switch (q.action) {
            case 'home': {
                forbiddenCache(resp);

                _args.msgs = [];
                var nameReg = /var username = (.*?);/;
                var headImgReg = /var headimg = (.*?);/;
                var nickReg = /var nickname = (.*?);/;
                var bizReg = /var __biz = (.*?);/;
                var msgsReg = /var msgList = '({.*?})';/;

                const $ = cheerio.load(response.body);

                var profile = {
                    biz: regSearch(response.body, bizReg),
                    name: regSearch(response.body, nameReg),
                    nick: regSearch(response.body, nickReg),
                    digest: $('.profile_info .profile_desc').text().trim(),
                    logoUrl: regSearch(response.body, headImgReg),
                    updateAt: moment(new Date()).valueOf()
                };

                _args.mq.send('profile', JSON.stringify(profile));

                try {
                    msgs = msgHelper.msgsMap(JSON.parse(regReplaceQuot(response.body, msgsReg)).list);

                    let opts = await msgHelper.applyFetchOpt(profile.nick, msgs);

                    opts.filteredMsgs.forEach((v, i, s) => _args.mq.send('msg', JSON.stringify(v)));
                    _args.mgr.addMsgs(profile.biz, opts.filteredMsgs);

                    var msg = _args.mgr.popMsg(profile.biz);
                    if (msg) {
                        response.body = injector.inject(response.body, scrollJs.replace('$__src', msg.src));
                        if (!opts.isContinue) {
                            response.body = injector.inject(response.body, redirectJs);
                        }
                    } else {
                        _args.hub.then(connection => {
                            connection.invoke('CompleteSubscription', profile.nick).catch(console.error);
                        }).catch(console.error);
                    }
                } catch (ex) {
                    _args.hub.then(connection => {
                        connection.invoke('CompleteSubscription', profile.nick).catch(console.error);
                    }).catch(console.error);
                }
            }
            case 'getmsg': {
                    var raw;
                try {
                    raw = JSON.parse(response.body);
                    msgs = msgHelper.msgsMap(JSON.parse(raw.general_msg_list).list);

                    brandSvr.single(q.__biz, async brand => {
                        let opts = await msgHelper.applyFetchOpt(brand.nick, msgs);

                        raw.can_msg_continue = opts.isContinue ? 1 : 0;
                        response.body = JSON.stringify(raw);

                        opts.filteredMsgs.forEach((v, i, s) => _args.mq.send('msg', JSON.stringify(v)));
                        _args.mgr.addMsgs(q.__biz, opts.filteredMsgs);
                    });
                } catch (e) {
                    if (raw) {
                        raw.can_msg_continue = 0;
                        response.body = JSON.stringify(raw);
                    }
                }
            }
            default: {
                break;
            }
        }
    }
}

module.exports = ProfileRule;